/*******************************************************************************
 * File name: 		timer.c
 * Description: 
 * Project: 		_framework
 * Target: 			LPC1788
 * Compiler: 		arm-none-eabi-gcc
 * Date: 			Sep 20, 2012
 * Author: 			kuba
 * Based on: 		---
 ******************************************************************************/

/*==============================================================================
 Includes
==============================================================================*/
# include "LPC177x_8x.h"
# include "hdr_sc.h"
# include "macros.h"

# include "timer.h"
/*==============================================================================
 Defines
==============================================================================*/
# define TIMERS			4		/* available timers */

/* register B definitions */
/* IR */
# define TIM_IR_MR0			SET_BIT(0)
# define TIM_IR_MR1			SET_BIT(1)
# define TIM_IR_MR2			SET_BIT(2)
# define TIM_IR_MR3			SET_BIT(3)
# define TIM_IR_CR0			SET_BIT(4)
# define TIM_IR_CR1			SET_BIT(5)
/* TCR */
# define TIM_TCR_CNT_EN 	SET_BIT(0)
# define TIM_TCR_CNT_RST	SET_BIT(1)
/* MCR */
# define TIM_MCR_MR0I		SET_BIT(0)
# define TIM_MCR_MR0R		SET_BIT(1)
# define TIM_MCR_MR0S		SET_BIT(2)
# define TIM_MCR_MR1I		SET_BIT(3)
# define TIM_MCR_MR1R		SET_BIT(4)
# define TIM_MCR_MR1S		SET_BIT(5)
# define TIM_MCR_MR2I		SET_BIT(6)
# define TIM_MCR_MR2R		SET_BIT(7)
# define TIM_MCR_MR2S		SET_BIT(8)
# define TIM_MCR_MR3I		SET_BIT(9)
# define TIM_MCR_MR3R		SET_BIT(10)
# define TIM_MCR_MR3S		SET_BIT(11)
/*==============================================================================
 Types
==============================================================================*/
enum tim {
	tim0,
	tim1,
	tim2,
	tim3
};


/*==============================================================================
 Globals
==============================================================================*/
static void (*userService[TIMERS])(void);

/*==============================================================================
 Static function definitions
==============================================================================*/
static void dummyService(void);

/*==============================================================================
 Global function definitions
==============================================================================*/
/*------------------------------------------------------------------------------
 function name: timer0Init
 description:	init timer 0
 parameters:	time after which interrupt will be fired and service called
 returned value: none
------------------------------------------------------------------------------*/
void timer0Init (const uint32 time, const enum irqPriority priority, void (*const service) (void))
{
	if (service == 0)
	{
		userService[tim0] = dummyService;
	}
	else
	{
		userService[tim0] = service;
	}

	NVIC_SetPriority(TIMER0_IRQn, priority);		/* set priority in NVIC */
	NVIC_EnableIRQ(TIMER0_IRQn);					/* enable interrupt in NVIC */

	LPC_SC->PCONP |= LPC_SC_PCONP_PCTIM0;			/* power on timer */
	LPC_TIM0->TCR = TIM_TCR_CNT_RST;				/* reset counter */
	LPC_TIM0->TCR = 0;								/* release reset */
	LPC_TIM0->TCR = TIM_TCR_CNT_EN;					/* enable counter */
	LPC_TIM0->IR = 0x3F;							/* clear interrupts */
	LPC_TIM0->PR = 0;
	LPC_TIM0->TC = 0;
	LPC_TIM0->PC = 0;
	LPC_TIM0->MR0 = time;
	LPC_TIM0->MCR |= TIM_MCR_MR0I | TIM_MCR_MR0R;	/* enable match interrupt + reset */
}

/*------------------------------------------------------------------------------
 function name: timer1Init
 description:	init timer 1
 parameters:	time after which interrupt will be fired and service called
 returned value: none
------------------------------------------------------------------------------*/
void timer1Init (const uint32 time, const enum irqPriority priority, void (*const service) (void))
{
	if (service == 0)
	{
		userService[tim1] = dummyService;
	}
	else
	{
		userService[tim1] = service;
	}

	NVIC_SetPriority(TIMER1_IRQn, priority);		/* set priority in NVIC */
	NVIC_EnableIRQ(TIMER1_IRQn);					/* enable interrupt in NVIC */

	LPC_SC->PCONP |= LPC_SC_PCONP_PCTIM1;			/* power on timer */
	LPC_TIM1->TCR = TIM_TCR_CNT_RST;				/* reset counter */
	LPC_TIM1->TCR = 0;								/* release reset */
	LPC_TIM1->TCR = TIM_TCR_CNT_EN;					/* enable counter */
	LPC_TIM1->IR = 0x3F;							/* clear interrupts */
	LPC_TIM1->PR = 0;
	LPC_TIM1->TC = 0;
	LPC_TIM1->PC = 0;
	LPC_TIM1->MR0 = time;
	LPC_TIM1->MCR |= TIM_MCR_MR0I | TIM_MCR_MR0R;	/* enable match interrupt + reset */
}

/*------------------------------------------------------------------------------
 function name: timer2Init
 description:	init timer 2
 parameters:	time after which interrupt will be fired and service called
 returned value: none
------------------------------------------------------------------------------*/
void timer2Init (const uint32 time, const enum irqPriority priority, void (*const service) (void))
{
	if (service == 0)
	{
		userService[tim2] = dummyService;
	}
	else
	{
		userService[tim2] = service;
	}

	NVIC_SetPriority(TIMER2_IRQn, priority);		/* set priority in NVIC */
	NVIC_EnableIRQ(TIMER2_IRQn);					/* enable interrupt in NVIC */

	LPC_SC->PCONP |= LPC_SC_PCONP_PCTIM2;			/* power on timer */
	LPC_TIM2->TCR = TIM_TCR_CNT_RST;				/* reset counter */
	LPC_TIM2->TCR = 0;								/* release reset */
	LPC_TIM2->TCR = TIM_TCR_CNT_EN;					/* enable counter */
	LPC_TIM2->IR = 0x3F;							/* clear interrupts */
	LPC_TIM2->PR = 0;
	LPC_TIM2->TC = 0;
	LPC_TIM2->PC = 0;
	LPC_TIM2->MR0 = time;
	LPC_TIM2->MCR |= TIM_MCR_MR0I | TIM_MCR_MR0R;	/* enable match interrupt + reset */
}

/*------------------------------------------------------------------------------
 function name: timer3Init
 description:	init timer 3
 parameters:	time after which interrupt will be fired and service called
 returned value: none
------------------------------------------------------------------------------*/
void timer3Init (const uint32 time, const enum irqPriority priority, void (*const service) (void))
{
	if (service == 0)
	{
		userService[tim3] = dummyService;
	}
	else
	{
		userService[tim3] = service;
	}

	NVIC_SetPriority(TIMER3_IRQn, priority);		/* set priority in NVIC */
	NVIC_EnableIRQ(TIMER3_IRQn);					/* enable interrupt in NVIC */

	LPC_SC->PCONP |= LPC_SC_PCONP_PCTIM3;			/* power on timer */
	LPC_TIM3->TCR = TIM_TCR_CNT_RST;				/* reset counter */
	LPC_TIM3->TCR = 0;								/* release reset */
	LPC_TIM3->TCR = TIM_TCR_CNT_EN;					/* enable counter */
	LPC_TIM3->IR = 0x3F;							/* clear interrupts */
	LPC_TIM3->PR = 0;
	LPC_TIM3->TC = 0;
	LPC_TIM3->PC = 0;
	LPC_TIM3->MR0 = time;
	LPC_TIM3->MCR |= TIM_MCR_MR0I | TIM_MCR_MR0R;	/* enable match interrupt + reset */
}
/*==============================================================================
 Static function definitions
==============================================================================*/
/*------------------------------------------------------------------------------
 function name: dummyService
 description:	dummy service
 parameters:	none
 returned value: none
------------------------------------------------------------------------------*/
static void dummyService(void)
{
	return;
}

/*==============================================================================
 ISR definitions
==============================================================================*/
/*------------------------------------------------------------------------------
 function name: TIMER0_IRQHandler
 description:	timer 0 ISR
 parameters:	none
 returned value: none
------------------------------------------------------------------------------*/
void TIMER0_IRQHandler (void)
{
	LPC_TIM0->IR |= TIM_IR_MR0;			/* clear interrupt */
	(*userService[tim0])();				/* call user service */
}

/*------------------------------------------------------------------------------
 function name: TIMER1_IRQHandler
 description:	timer 1 ISR
 parameters:	none
 returned value: none
------------------------------------------------------------------------------*/
void TIMER1_IRQHandler (void)
{
	LPC_TIM1->IR |= TIM_IR_MR0;			/* clear interrupt */
	(*userService[tim1])();				/* call user service */
}

/*------------------------------------------------------------------------------
 function name: TIMER2_IRQHandler
 description:	timer 2 ISR
 parameters:	none
 returned value: none
------------------------------------------------------------------------------*/
void TIMER2_IRQHandler (void)
{
	LPC_TIM2->IR |= TIM_IR_MR0;			/* clear interrupt */
	(*userService[tim2])();				/* call user service */
}

/*------------------------------------------------------------------------------
 function name: TIMER3_IRQHandler
 description:	timer 3 ISR
 parameters:	none
 returned value: none
------------------------------------------------------------------------------*/
void TIMER3_IRQHandler (void)
{
	LPC_TIM3->IR |= TIM_IR_MR0;			/* clear interrupt */
	(*userService[tim3])();				/* call user service */
}
/******************************************************************************
* END OF FILE
******************************************************************************/


